home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bint / b1tlt.c < prev    next >
C/C++ Source or Header  |  1988-11-24  |  16KB  |  669 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2.  
  3. /*
  4.   $Header: b1tlt.c,v 1.4 85/08/22 16:53:20 timo Exp $
  5. */
  6.  
  7. /* generic routines for B texts, lists and tables */
  8.  
  9. #include "b.h"
  10. #include "b0fea.h"
  11. #include "b1obj.h"
  12. #ifndef INTEGRATION
  13. #include "b0con.h"
  14. #include "b1btr.h"
  15. #include "b1val.h"
  16. #endif
  17. #include "b1tlt.h"
  18. #include "b3err.h"
  19.  
  20. #ifndef INTEGRATION
  21.  
  22. /* From b1lta.c */
  23. int l2size();
  24. value l2min(), l2max();
  25.  
  26. Visible value mk_elt() { /* {}, internal only */
  27.     value e = grab_tlt(ELT, Lt);
  28.     Root(e) = Bnil;
  29.     return e;
  30. }
  31.  
  32. Visible bool empty(v) value v; { /* #v=0, internal only */
  33.     switch (Type(v)) {
  34.     case ELT:
  35.     case Lis:
  36.     case Tex:
  37.     case Tab:
  38.         return Root(v) EQ Bnil;
  39.     default:
  40.         return No;
  41.         /* Some routines must test empty(t) end return an error
  42.            message if it fails, before testing Type(t).
  43.            In this way, they won't give the wrong error message. */
  44.     }
  45. }
  46.  
  47. /* return size of (number of items in) dependent tree */
  48.  
  49. Hidden value treesize(pnode) btreeptr pnode; {
  50.     int psize;
  51.     value vsize, childsize, u;
  52.     intlet l;
  53.     psize = Size(pnode);
  54.     if (psize EQ Bigsize) {
  55.     switch (Flag(pnode)) {        
  56.     case Inner:
  57.         vsize = mk_integer((int) Lim(pnode));
  58.         for (l = 0; l <= Lim(pnode); l++) {
  59.         childsize = treesize(Ptr(pnode, l));
  60.         u = vsize;
  61.         vsize = sum(vsize, childsize);
  62.         release(u);
  63.         release(childsize);
  64.         }
  65.         break;
  66.     case Irange: 
  67.         u = diff(Upbval(pnode), Lwbval(pnode));
  68.         vsize = sum(u, one);
  69.         release(u);
  70.         break;
  71.     case Bottom: 
  72.     case Crange: 
  73.         syserr(MESS(1700, "Bigsize in Bottom or Crange"));
  74.     }
  75.     return(vsize);
  76.     }
  77.     return mk_integer(psize);
  78. }
  79.  
  80. Visible value size(t) value t; { /* #t */
  81.     int tsize;
  82.     switch (Type(t)) {
  83.     case ELT:
  84.     case Lis:
  85.     case Tex:
  86.     case Tab:
  87.         tsize = Tltsize(t);
  88.         if (tsize EQ Bigsize) return treesize(Root(t));
  89.         return mk_integer(tsize);
  90.     default:
  91.         reqerr(MESS(1701, "in #t, t is not a text, list or table"));
  92.         return zero;
  93.     }
  94. }
  95.  
  96. Visible value th_of(num, v) value num, v; { /* num th'of v */
  97.     value m= Vnil;
  98.     if (!Is_tlt(v))
  99.         error(MESS(1702, "in n th'of t, t is not a text, list or table"));
  100.     else if (!Is_number(num))
  101.         error(MESS(1703, "in n th'of t, n is not a number"));
  102.     else if (empty(v))
  103.         error(MESS(1704, "in n th'of t, t is empty"));
  104.     else if (numcomp(num, one) < 0)
  105.         error(MESS(1705, "in n th'of t, n is < 1"));
  106.     else {
  107.         /*RANGES?*/
  108.         m= thof(intval(num), v);
  109.         if (m == Vnil && still_ok)
  110.             error(MESS(1706, "in n th'of t, n exceeds #t"));
  111.     }
  112.     return m;
  113. }
  114.  
  115. /*
  116.  * 'Walktree' handles functions on texts and associates of tables.
  117.  * The actual function performed is determined by the 'visit' function.
  118.  * The tree is walked (possibly recursively) and all items are visited.
  119.  * The return value of walktree() and visit() is used to determine whether
  120.  * the walk should continue (Yes == continue, No == stop now).
  121.  * Global variables are used to communicate the result, and the parameters
  122.  * of the function. The naming convention is according to "e func t".
  123.  */
  124.  
  125. Hidden intlet tt;        /* type of walked value t */
  126. Hidden intlet wt;        /* width of items in walked value t */
  127. Hidden value ve;         /* value of e, if func is dyadic */
  128. Hidden char ce;         /* C char in e, if t is a text */
  129.  
  130. Hidden int count;         /* result of size2 */
  131. Hidden bool found;         /* result for in */
  132. Hidden intlet m_char;         /* result for min/max on texts */
  133. Hidden value m_val;        /* result for min/max on tables */
  134.  
  135. #define Lowchar (-Maxintlet)    /* -infinity for characters */
  136. #define Highchar (Maxintlet)    /* +infinity */
  137.  
  138. Hidden bool walktree(p, visit) btreeptr p; bool (*visit)(); {
  139.     intlet l;
  140.     
  141.     if (p EQ Bnil) return Yes; /* i.e., not found (used by in() !) */
  142.     for (l=0; l < Lim(p); l++) {
  143.         switch (Flag(p)) {
  144.         case Inner:
  145.             if (!walktree(Ptr(p, l), visit) || !still_ok)
  146.                 return No;
  147.             if (!(*visit)(Piitm(p, l, wt)) || !still_ok)
  148.                 return No;
  149.             break;
  150.         case Bottom:
  151.             if (!(*visit)(Pbitm(p, l, wt)) || !still_ok)
  152.                 return No;
  153.         }
  154.     }
  155.     return Flag(p) EQ Bottom || walktree(Ptr(p, l), visit);
  156. }
  157.  
  158. /* Common code for min/max-1/2, size2, in. */
  159.  
  160. Hidden Procedure tlt_func(e, t, where, li_func, te_visit, ta_visit)
  161.     value e, t;             /* [e] func t */
  162.     string where;             /* "in [e] func_name t" */
  163.     value (*li_func)();         /* func for lists */
  164.     bool (*te_visit)(), (*ta_visit)(); /* 'visit' for walktree */
  165. {
  166.     m_val = Vnil;
  167.     if (empty(t)) {
  168.         error3(MESSMAKE(where), Vnil, MESS(1707, ", t is empty"));
  169.         return;
  170.     }
  171.     wt = Itemwidth(Itemtype(t));
  172.     tt = Type(t);
  173.     switch (tt) {
  174.     case Lis:
  175.         m_val = (*li_func)(e, t);
  176.         break;
  177.     case Tex:
  178.         if (e NE Vnil) {
  179.             if (!Character(e)) {
  180.                 error3(MESSMAKE(where), Vnil,
  181.             MESS(1708, ", t is a text, but e is not a character"));
  182.                 return;
  183.             }
  184.             ce = Bchar(Root(e), 0);
  185.         }
  186.         found = !walktree(Root(t), te_visit);
  187.         if (m_char NE Lowchar && m_char NE Highchar)
  188.             m_val = mkchar(m_char);
  189.         break;
  190.     case Tab:
  191.         ve = e;
  192.         found = !walktree(Root(t), ta_visit);
  193.         break;
  194.     default:
  195.         error3(MESSMAKE(where), Vnil,
  196.             MESS(1709, ", t is not a text list or table"));
  197.     }
  198. }
  199.  
  200. Hidden value li2size(e, t) value e, t; {
  201.     count = l2size(e, t);
  202.     return Vnil;
  203. }
  204.  
  205. Hidden bool te2size(pitm) itemptr pitm; {
  206.     if (ce EQ Charval(pitm))
  207.         count++;
  208.     return Yes;
  209. }
  210.  
  211. Hidden bool ta2size(pitm) itemptr pitm; {
  212.     if (compare(ve, Ascval(pitm)) EQ 0)
  213.         count++;
  214.     return Yes;
  215. }
  216.  
  217. Visible value size2(e, t) value e, t; { /* e#t */
  218.     if (empty(t)) /* Must check here because tlt_func would complain */
  219.         return copy(zero);
  220.     m_char = Lowchar;
  221.     count = 0;
  222.     tlt_func(e, t, "in e#t", li2size, te2size, ta2size);
  223.     return mk_integer(count);
  224. }
  225.  
  226. Hidden value li_in(e, t) value e, t; {
  227.     found = in_keys(e, t);
  228.     return Vnil;
  229. }
  230.     
  231. Hidden bool te_in(pitm) itemptr pitm; {
  232.     return Charval(pitm) NE ce;
  233. }
  234.  
  235. Hidden bool ta_in(pitm) itemptr pitm; {
  236.     return compare(ve, Ascval(pitm)) NE 0;
  237. }
  238.  
  239. Visible bool in(e, t) value e, t; {
  240.     if (empty(t)) /* Must check here because tlt_func would complain */
  241.         return No;
  242.     m_char = Lowchar;
  243.     found = No;
  244.     tlt_func(e, t, "in the test e in t", li_in, te_in, ta_in);
  245.     return found;
  246. }
  247.  
  248. Hidden value li_min(e, t) value e, t; {
  249.     return th_of(one, t);
  250. }
  251.  
  252. Hidden bool te_min(pitm) itemptr pitm; {
  253.     if (m_char > Charval(pitm))
  254.         m_char = Charval(pitm);
  255.     return Yes;
  256. }
  257.  
  258. Hidden bool ta_min(pitm) itemptr pitm; {
  259.     if (m_val EQ Vnil || compare(m_val, Ascval(pitm)) > 0) {
  260.         release(m_val);
  261.         m_val = copy(Ascval(pitm));
  262.     }
  263.     return Yes;
  264. }
  265.  
  266. Visible value min1(t) value t; {
  267.     m_char = Highchar;
  268.     tlt_func(Vnil, t, "in min t", li_min, te_min, ta_min);
  269.     return m_val;
  270. }
  271.  
  272. Hidden value li_max(e, t) value e, t; {
  273.     value v= size(t);
  274.     m_val = th_of(v, t);
  275.     release(v);
  276.     return m_val;
  277. }
  278.  
  279. Hidden bool te_max(pitm) itemptr pitm; {
  280.     if (m_char < Charval(pitm))
  281.         m_char = Charval(pitm);
  282.     return Yes;
  283. }
  284.  
  285. Hidden bool ta_max(pitm) itemptr pitm; {
  286.     if (m_val EQ Vnil || compare(Ascval(pitm), m_val) > 0) {
  287.         release(m_val);
  288.         m_val = copy(Ascval(pitm));
  289.     }
  290.     return Yes;
  291. }
  292.  
  293. Visible value max1(t) value t; {
  294.     m_char = Lowchar;
  295.     tlt_func(Vnil, t, "in max t", li_max, te_max, ta_max);
  296.     return m_val;
  297. }
  298.  
  299. Hidden bool te2min(pitm) itemptr pitm; {
  300.     if (m_char > Charval(pitm) && Charval(pitm) > ce) {
  301.         m_char = Charval(pitm);
  302.     }
  303.     return Yes;
  304. }
  305.  
  306. Hidden bool ta2min(pitm) itemptr pitm; {
  307.     if (compare(Ascval(pitm), ve) > 0
  308.         &&
  309.         (m_val EQ Vnil || compare(m_val, Ascval(pitm)) > 0)) {
  310.         release(m_val);
  311.         m_val = copy(Ascval(pitm));
  312.     }
  313.     return Yes;
  314. }
  315.  
  316. Visible value min2(e, t) value e, t; {
  317.     m_char = Highchar;
  318.     tlt_func(e, t, "in e min t", l2min, te2min, ta2min);
  319.     if (m_val EQ Vnil && still_ok)
  320.         reqerr(MESS(1710, "in e min t, no element of t exceeds e"));
  321.     return m_val;
  322. }
  323.  
  324. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  325.  
  326. Hidden bool te2max(pitm) itemptr pitm; {
  327.     if (ce > Charval(pitm) && Charval(pitm) > m_char) {
  328.         m_char = Charval(pitm);
  329.     }
  330.     return Yes;
  331. }
  332.  
  333. Hidden bool ta2max(pitm) itemptr pitm; {
  334.     if (compare(ve, Ascval(pitm)) > 0
  335.         &&
  336.         (m_val EQ Vnil || compare(Ascval(pitm), m_val) > 0)) {
  337.         release(m_val);
  338.         m_val = copy(Ascval(pitm));
  339.     }
  340.     return Yes;
  341. }
  342.  
  343. Visible value max2(e, t) value e, t; {
  344.     m_char = Lowchar;
  345.     tlt_func(e, t, "in e max t", l2max, te2max, ta2max);
  346.     if (m_val EQ Vnil && still_ok)
  347.         reqerr(MESS(1711, "in e max t, no element of t is less than e"));
  348.     return m_val;
  349. }
  350.  
  351. #else INTEGRATION
  352.  
  353. Visible value mk_elt() { return grab_elt(); }
  354.  
  355. Visible value size(x) value x; { /* monadic # operator */
  356.     if (!Is_tlt(x))
  357.         error(MESS(1712, "in #t, t is not a text, list or table"));
  358.     return mk_integer((int) Length(x));
  359. }
  360.  
  361. #define Lisent(tp,k) (*(tp+(k)))
  362.  
  363. Visible value size2(v, t) value v, t; { /* Dyadic # operator */
  364.     intlet len= Length(t), n= 0, k; value *tp= Ats(t);
  365.     if (!Is_tlt(t)) {
  366.         error(MESS(1713, "in e#t, t is not a text, list or table"));
  367.         return mk_integer((int) n);
  368.     }
  369.     switch (Type(t)) {
  370.     case Tex:
  371.         {string cp= (string)tp; char c;
  372.             if (Type(v) != Tex)
  373.                 error(MESS(1714, "in e#t, t is a text but e is not"));
  374.             if (Length(v) != 1)
  375.                 error(MESS(1715, "in e#t, e is a text but not a character"));
  376.             c= *Str(v);
  377.             Overall if (*cp++ == c) n++;
  378.         } break;
  379.     case ELT:
  380.         break;
  381.     case Lis:
  382.         {intlet lo= -1, mi, xx, mm, hi= len; relation c;
  383.         bins:    if (hi-lo < 2) break;
  384.             mi= (lo+hi)/2;
  385.             if ((c= compare(v, Lisent(tp,mi))) == 0) goto some;
  386.             if (c < 0) hi= mi; else lo= mi;
  387.             goto bins;
  388.         some:    xx= mi;
  389.             while (xx-lo > 1) {
  390.                 mm= (lo+xx)/2;
  391.                 if (compare(v, Lisent(tp,mm)) == 0) xx= mm;
  392.                 else lo= mm;
  393.             }
  394.             xx= mi;
  395.             while (hi-xx > 1) {
  396.                 mm= (xx+hi)/2;
  397.                 if (compare(v, Lisent(tp,mm)) == 0) xx= mm;
  398.                 else hi= mm;
  399.             }
  400.             n= hi-lo-1;
  401.         } break;
  402.     case Tab:
  403.         Overall if (compare(v, Dts(*tp++)) == 0) n++;
  404.         break;
  405.     default:
  406.         syserr(MESS(1716, "e#t with non text, list or table"));
  407.         break;
  408.     }
  409.     return mk_integer((int) n);
  410. }
  411.  
  412. Hidden bool less(r) relation r;    { return r<0; }
  413. Hidden bool greater(r) relation r; { return r>0; }
  414.  
  415. Hidden value mm1(t, rel) value t; bool (*rel)(); {
  416.     intlet len= Length(t), k; value m, *tp= Ats(t);
  417.     switch (Type(t)) {
  418.     case Tex:
  419.         {string cp= (string) tp; char mc= '\0', mm[2];
  420.             Overall {
  421.                 if (mc == '\0' || ((*rel)(*cp < mc ? -1 : (*cp > mc ? 1 : 0))))
  422.                     mc= *cp;
  423.                 cp++;
  424.             }
  425.             mm[0]= mc; mm[1]= '\0';
  426.             m= mk_text(mm);
  427.         } break;
  428.     case Lis:
  429.         if ((*rel)(-1)) /*min*/ m= copy(*Ats(t));
  430.         else m= copy(*(Ats(t)+len-1));
  431.         break;
  432.     case Tab:
  433.         {value dm= Vnil;
  434.             Overall {
  435.                 if (dm == Vnil || (*rel)(compare(Dts(*tp), dm)))
  436.                     dm= Dts(*tp);
  437.                 tp++;
  438.             }
  439.             m= copy(dm);
  440.         } break;
  441.     default:
  442.         syserr(MESS(1717, "min or max t, with non text, list or table"));
  443.     }
  444.     return m;
  445. }
  446.  
  447. #ifdef NO_ABS
  448.  
  449. Hidden int abs(i) int i; {
  450.     return i >= 0 ? i : -i;
  451. }
  452.  
  453. #endif
  454.  
  455. Hidden value mm2(v, t, rel) value v, t; bool (*rel)(); {
  456.     intlet len= Length(t), k; value m= Vnil, *tp= Ats(t);
  457.     switch (Type(t)) {
  458.     case Tex:
  459.         {string cp= (string) tp; char c, mc= '\0', mm[2];
  460.             c= *Str(v);
  461.             Overall {
  462.                 if ((*rel)(c < *cp ? -1 : c > *cp ? 1 : 0)) {
  463.                     if (mc == '\0' || (*rel)(*cp < mc ? -1 : *cp>mc ? 1 : 0))
  464.                         mc= *cp;
  465.                 }
  466.                 cp++;
  467.             }
  468.             if (mc != '\0') {
  469.                 mm[0]= mc; mm[1]= '\0';
  470.                 m= mk_text(mm);
  471.             }
  472.         } break;
  473.     case Lis:
  474.         {intlet lim1, mid, lim2;
  475.             if ((*rel)(-1)) { /*min*/
  476.                 lim1= 1; lim2= len-1;
  477.             } else {
  478.                 lim2= 1; lim1= len-1;
  479.             }
  480.             if (!(*rel)(compare(v, Lisent(tp,lim2)))) break;
  481.             if (len == 1 || (*rel)(compare(v, Lisent(tp,lim1)))) {
  482.                 m= copy(Lisent(tp,lim1));
  483.                 break;
  484.             }
  485.             /* v rel tp[lim2] && !(v rel tp[lim1]) */
  486.             while (abs(lim2-lim1) > 1) {
  487.                 mid= (lim1+lim2)/2;
  488.                 if ((*rel)(compare(v, Lisent(tp,mid)))) lim2= mid;
  489.                 else lim1= mid;
  490.             }
  491.             m= copy(Lisent(tp,lim2));
  492.         } break;
  493.     case Tab:
  494.         {value dm= Vnil;
  495.             Overall {
  496.                 if ((*rel)(compare(v, Dts(*tp)))) {
  497.                     if (dm == Vnil ||
  498.                         (*rel)(compare(Dts(*tp), dm)))
  499.                         dm= Dts(*tp);
  500.                 }
  501.                 tp++;
  502.             }
  503.             if (dm != Vnil) m= copy(dm);
  504.         } break;
  505.     default:
  506.         syserr(MESS(1718, "min2 or max2 with non text, list or table"));
  507.         break;
  508.     }
  509.     return m;
  510. }
  511.  
  512. Visible value min1(t) value t; { /* Monadic min */
  513.     value m= Vnil;
  514.     if (!Is_tlt(t))
  515.         error(MESS(1719, "in min t, t is not a text, list or table"));
  516.     else if (Length(t) == 0)
  517.         error(MESS(1720, "in min t, t is empty"));
  518.     else m= mm1(t, less);
  519.     return m;
  520. }
  521.  
  522. Visible value min2(v, t) value v, t; {
  523.     value m= Vnil;
  524.     if (!Is_tlt(t))
  525.         error(MESS(1721, "in e min t, t is not a text, list or table"));
  526.     else if (Length(t) == 0)
  527.         error(MESS(1722, "in e min t, t is empty"));
  528.     else if (Is_text(t)) {
  529.         if (!Is_text(v))
  530.             error(MESS(1723, "in e min t, t is a text but e is not"));
  531.         else if (Length(v) != 1)
  532.             error(MESS(1724, "in e min t, e is a text but not a character"));
  533.     }
  534.     if (still_ok) {
  535.         m= mm2(v, t, less);
  536.         if (m == Vnil)
  537.             error(MESS(1725, "in e min t, no element of t exceeds e"));
  538.     }
  539.     return m;
  540. }
  541.  
  542. Visible value max1(t) value t; {
  543.     value m= Vnil;
  544.     if (!Is_tlt(t))
  545.         error(MESS(1726, "in max t, t is not a text, list or table"));
  546.     else if (Length(t) == 0)
  547.         error(MESS(1727, "in max t, t is empty"));
  548.     else m= mm1(t, greater);
  549.     return m;
  550. }
  551.  
  552. Visible value max2(v, t) value v, t; {
  553.     value m= Vnil;
  554.     if (!Is_tlt(t))
  555.         error(MESS(1728, "in e max t, t is not a text, list or table"));
  556.     else if (Length(t) == 0)
  557.         error(MESS(1729, "in e max t, t is empty"));
  558.     else if (Is_text(t)) {
  559.         if (!Is_text(v))
  560.             error(MESS(1730, "in e max t, t is a text but e is not"));
  561.         else if (Length(v) != 1)
  562.             error(MESS(1731, "in e max t, e is a text but not a character"));
  563.     }
  564.     if (still_ok) {
  565.         m= mm2(v, t, greater);
  566.         if (m == Vnil)
  567.             error(MESS(1732, "in e max t, no element of t is less than e"));
  568.     }
  569.     return m;
  570. }
  571.  
  572. Visible value th_of(n, t) value n, t; {
  573.     return thof(intval(n), t);
  574. }
  575.  
  576. Visible value thof(n, t) int n; value t; {
  577.     intlet len= Length(t); value w= Vnil;
  578.     if (!Is_tlt(t))
  579.         error(MESS(1733, "in n th'of t, t is not a text, list or table"));
  580.     else if (n <= 0 || n > len)
  581.         error(MESS(1734, "in n th'of t, n is out of bounds"));
  582.     else {
  583.         switch (Type(t)) {
  584.         case Tex:
  585.             {char ww[2];
  586.                 ww[0]= *(Str(t)+n-1); ww[1]= '\0';
  587.                 w= mk_text(ww);
  588.             } break;
  589.         case Lis:
  590.             w= copy(*(Ats(t)+n-1));
  591.             break;
  592.         case Tab:
  593.             w= copy(Dts(*(Ats(t)+n-1)));
  594.             break;
  595.         default:
  596.             syserr(MESS(1735, "th'of with non text, list or table"));
  597.         }
  598.     }
  599.     return w;
  600. }
  601.  
  602. Visible bool found(elem, v, probe, where)
  603.     value (*elem)(), v, probe; intlet *where;
  604.     /* think of elem(v,lo-1) as -Infinity and elem(v,hi+1) as +Infinity.
  605.        found and where at the end satisfy:
  606.        SELECT:
  607.            SOME k IN {lo..hi} HAS probe = elem(v,k):
  608.            found = Yes AND where = k
  609.            ELSE: found = No AND elem(v,where-1) < probe < elem(v,where).
  610.     */
  611. {relation c; intlet lo=0, hi= Length(v)-1;
  612.     if (lo > hi) { *where= lo; return No; }
  613.     if ((c= compare(probe, (*elem)(v, lo))) == 0) {*where= lo; return Yes; }
  614.     if (c < 0) { *where=lo; return No; }
  615.     if (lo == hi) { *where=hi+1; return No; }
  616.     if ((c= compare(probe, (*elem)(v, hi))) == 0) { *where=hi; return Yes; }
  617.     if (c > 0) { *where=hi+1; return No; }
  618.     /* elem(lo) < probe < elem(hi) */
  619.     while (hi-lo > 1) {
  620.         if ((c= compare(probe, (*elem)(v, (lo+hi)/2))) == 0) {
  621.             *where= (lo+hi)/2; return Yes;
  622.         }
  623.         if (c < 0) hi= (lo+hi)/2; else lo= (lo+hi)/2;
  624.     }
  625.     *where= hi; return No;
  626. }
  627.  
  628. Visible bool in(v, t) value v, t; {
  629.     intlet where, k, len= Length(t); value *tp= Ats(t);
  630.     if (!Is_tlt(t)) {
  631.         error(MESS(1736, "in the test e in t, t is not a text, list or table"));
  632.         return No;
  633.     }
  634.     switch (Type(t)) {
  635.     case Tex:
  636.         if (Type(v) != Tex)
  637.             error(MESS(1737, "in the test e in t, t is a text but e is not"));
  638.         else if (Length(v) != 1)
  639.             error(MESS(1738, "in the test e in t, e is a text but not a character"));
  640.         else return index((string) tp, *Str(v)) != 0;
  641.         return No;
  642.     case ELT:
  643.         return No;
  644.     case Lis:
  645.         return found(list_elem, t, v, &where);
  646.     case Tab:
  647.         Overall if (compare(v, Dts(*tp++)) == 0) return Yes;
  648.         return No;
  649.     default:
  650.         syserr(MESS(1739, "e in t with non text, list or table"));
  651.         return No;
  652.     }
  653. }
  654.  
  655. Visible bool empty(v) value v; {
  656.     switch (Type(v)) {
  657.     case Tex:
  658.     case Lis:
  659.     case Tab:
  660.     case ELT:
  661.         return (Length(v) == 0);
  662.     default:
  663.         syserr(MESS(1740, "empty() on non tlt value"));
  664.         return (No);
  665.     }
  666. }
  667.  
  668. #endif INTEGRATION
  669.